﻿// Gateway.Api 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// 
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// 
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using System.Threading.Channels;
using Aurora.AI.Domain.Domain;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Aurora.AI.Gateway.Services;
/// <summary>
/// 日志 event bus
/// </summary>
public class ChatLoggerEventBus
{
    private readonly Channel<ChatLogger> _loggerChannel = Channel.CreateUnbounded<ChatLogger>();
    private readonly CancellationTokenSource _cts = new();

    public ChatLoggerEventBus(ILogger<ChatLoggerEventBus> logger, IServiceScopeFactory serviceScopeFactory)
    {
        Task.Run(async () =>
        {
            while (_cts.Token.IsCancellationRequested == false)
            {
                await foreach (var @event in _loggerChannel.Reader.ReadAllAsync(_cts.Token))
                {
                    try
                    {
                        // 写入日志
                        await serviceScopeFactory.CreateScope().ServiceProvider.GetService<ChatLoggerService>().Create(@event);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"ChannelEventBus Error: {e.Message}");
                    }
                }
            }
        }, _cts.Token);
    }

    public async ValueTask PublishAsync(ChatLogger @event)
    {
        await _loggerChannel.Writer.WriteAsync(@event).ConfigureAwait(false);
    }
    /// <summary>
    /// 消费日志
    /// </summary>
    /// <param name="content"></param>
    /// <param name="model"></param>
    /// <param name="promptTokens"></param>
    /// <param name="completionTokens"></param>
    /// <param name="quota"></param>
    /// <param name="tokenName"></param>
    /// <param name="userName"></param>
    /// <param name="userId"></param>
    /// <param name="channelId"></param>
    /// <param name="channelName"></param>
    /// <param name="ip"></param>
    /// <param name="userAgent"></param>
    /// <returns></returns>
    public async Task ConsumeAsync(string content, string model, int promptTokens, int completionTokens,
        int quota, string? tokenName, string? userName, string? userId, string? channelId, string? channelName,
        string ip, string userAgent)
    {
        var logger = new ChatLogger()
        {
            Type = 1,
            Content = content,
            ModelName = model,
            PromptTokens = promptTokens,
            CompletionTokens = completionTokens,
            IP = ip,
            UserAgent = userAgent,
            Quota = quota,
            TokenName = tokenName,
            UserName = userName,
            UserId = userId,
            ChannelId = channelId,
            ChannelName = channelName,
            CreationTime = DateTime.Now,
            Creator = userId,
            ModificationTime = DateTime.Now,
            Modifier = userId
        };
        // 借助 channel
        await PublishAsync(logger);
    }
    public void Dispose()
    {
        _cts.Dispose();
    }
}